﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace DCT.Model
{
    public class XMLModel
    {
        static public bool LoadProject(string projectFile, ICollection<DeviceBaseModel> deviceModels, ICollection<DeviceBaseGraphModel> deviceGraphModels)
        {
            deviceModels.Clear();
            deviceGraphModels.Clear();

            XElement prpject = XElement.Load(projectFile);
            XElement device = prpject.Element(Resource.XMLModel_Devices);
            XElement graph = prpject.Element(Resource.XMLModel_Graphs);

            foreach (XElement devices in device.Elements())
            {
                switch (devices.Name.LocalName)
                {
                    case "TrackSegments":
                        foreach (XElement e in devices.Elements())
                        {
                            TrackSegmentModel tsModel = new TrackSegmentModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceType = (string)e.Element(Resource.XMLModel_Device_Type)
                            };

                            deviceModels.Add(tsModel);
                        }
                        break;
                    case "Switchs":
                        foreach (XElement e in devices.Elements())
                        {
                            SwitchModel swModel = new SwitchModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceType = (string)e.Element(Resource.XMLModel_Device_Type)
                            };

                            deviceModels.Add(swModel);
                        }
                        break;
                    case "Signals":
                        foreach (XElement e in devices.Elements())
                        {
                            SignalModel sgModel = new SignalModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceType = (string)e.Element(Resource.XMLModel_Device_Type)
                            };

                            deviceModels.Add(sgModel);
                        }
                        break;
                    case "Axles":
                        foreach (XElement e in devices.Elements())
                        {
                            AxleModel axModel = new AxleModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceType = (string)e.Element(Resource.XMLModel_Device_Type)
                            };

                            deviceModels.Add(axModel);
                        }
                        break;
                    case "Platforms":
                        foreach (XElement e in devices.Elements())
                        {
                            PlatformModel pfModel = new PlatformModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceType = (string)e.Element(Resource.XMLModel_Device_Type)
                            };

                            deviceModels.Add(pfModel);
                        }
                        break;
                    case "MiscellaneousDevices":
                        foreach (XElement e in devices.Elements())
                        {
                            MiscellaneousDeviceModel dmModel = new MiscellaneousDeviceModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceType = (string)e.Element(Resource.XMLModel_Device_Type),
                                MDSubType = (string)e.Element(Resource.XMLModel_MiscellaneousDevice_MDSubType)
                            };

                            deviceModels.Add(dmModel);
                        }
                        break;
                    default:
                        break;
                }
            }

            foreach (XElement devices in graph.Elements())
            {
                switch (devices.Name.LocalName)
                {
                    case "TrackSegments":
                        foreach (XElement e in devices.Elements())
                        {
                            TrackSegmentGraphModel tsGraphModel = new TrackSegmentGraphModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceName = (string)e.Element(Resource.XMLModel_Graph_Name),
                                GraphType = (string)e.Element(Resource.XMLModel_Graph_Type),
                                StartPoint = (string)e.Element(Resource.XMLModel_TrackSegment_StartPoint),
                                EndPoint = (string)e.Element(Resource.XMLModel_TrackSegment_EndPoint),
                                DeviceWidth = 900,
                                DeviceHeight = 900
                            };

                            tsGraphModel.Graph.GraphID = deviceGraphModels.Count;
                            tsGraphModel.TrackSegment.GraphID = deviceGraphModels.Count;

                            deviceGraphModels.Add(tsGraphModel);
                        }
                        break;
                    case "Switchs":
                        foreach (XElement e in devices.Elements())
                        {
                            SwitchGraphModel swGraphModel = new SwitchGraphModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceName = (string)e.Element(Resource.XMLModel_Graph_Name),
                                GraphType = (string)e.Element(Resource.XMLModel_Graph_Type),
                                MergePoint = (string)e.Element(Resource.XMLModel_Switch_MergePoint),
                                NormalPoint = (string)e.Element(Resource.XMLModel_Switch_NormalPoint),
                                ReversePoint = (string)e.Element(Resource.XMLModel_Switch_ReversePoint),
                                DeviceWidth = 900,
                                DeviceHeight = 900
                            };

                            swGraphModel.Graph.GraphID = deviceGraphModels.Count;
                            swGraphModel.Switch.GraphID = deviceGraphModels.Count;

                            deviceGraphModels.Add(swGraphModel);
                        }
                        break;
                    case "Signals":
                        foreach (XElement e in devices.Elements())
                        {
                            SignalGraphModel sgGraphModel = new SignalGraphModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceName = (string)e.Element(Resource.XMLModel_Graph_Name),
                                GraphType = (string)e.Element(Resource.XMLModel_Graph_Type),
                                PositionPoint = (string)e.Element(Resource.XMLModel_Graph_PositionPoint),
                                DeviceAngle = int.Parse((string)e.Element(Resource.XMLModel_Graph_Angle)),
                                DeviceWidth = int.Parse((string)e.Element(Resource.XMLModel_Graph_Width)),
                                DeviceHeight = int.Parse((string)e.Element(Resource.XMLModel_Graph_Height)),
                            };

                            sgGraphModel.Graph.GraphID = deviceGraphModels.Count;
                            sgGraphModel.Signal.GraphID = deviceGraphModels.Count;

                            deviceGraphModels.Add(sgGraphModel);
                        }
                        break;
                    case "Axles":
                        foreach (XElement e in devices.Elements())
                        {
                            AxleGraphModel axGraphModel = new AxleGraphModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceName = (string)e.Element(Resource.XMLModel_Graph_Name),
                                GraphType = (string)e.Element(Resource.XMLModel_Graph_Type),
                                PositionPoint = (string)e.Element(Resource.XMLModel_Graph_PositionPoint),
                                DeviceAngle = int.Parse((string)e.Element(Resource.XMLModel_Graph_Angle)),
                                DeviceWidth = int.Parse((string)e.Element(Resource.XMLModel_Graph_Width)),
                                DeviceHeight = int.Parse((string)e.Element(Resource.XMLModel_Graph_Height)),
                            };

                            axGraphModel.Graph.GraphID = deviceGraphModels.Count;
                            axGraphModel.Axle.GraphID = deviceGraphModels.Count;

                            deviceGraphModels.Add(axGraphModel);
                        }
                        break;
                    case "Platforms":
                        foreach (XElement e in devices.Elements())
                        {
                            PlatformGraphModel pfGraphModel = new PlatformGraphModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceName = (string)e.Element(Resource.XMLModel_Graph_Name),
                                GraphType = (string)e.Element(Resource.XMLModel_Graph_Type),
                                PositionPoint = (string)e.Element(Resource.XMLModel_Graph_PositionPoint),
                                DeviceAngle = int.Parse((string)e.Element(Resource.XMLModel_Graph_Angle)),
                                DeviceWidth = int.Parse((string)e.Element(Resource.XMLModel_Graph_Width)),
                                DeviceHeight = int.Parse((string)e.Element(Resource.XMLModel_Graph_Height)),
                            };

                            pfGraphModel.Graph.GraphID = deviceGraphModels.Count;
                            pfGraphModel.Platform.GraphID = deviceGraphModels.Count;

                            deviceGraphModels.Add(pfGraphModel);
                        }
                        break;
                    case "MiscellaneousDevices":
                        foreach (XElement e in devices.Elements())
                        {
                            MiscellaneousDeviceGraphModel dmGraphModel = new MiscellaneousDeviceGraphModel
                            {
                                DeviceID = HexStringToInt((string)e.Element(Resource.XMLModel_Device_ID)),
                                DeviceName = (string)e.Element(Resource.XMLModel_Graph_Name),
                                GraphType = (string)e.Element(Resource.XMLModel_Graph_Type),
                                PositionPoint = (string)e.Element(Resource.XMLModel_Graph_PositionPoint),
                                DeviceAngle = int.Parse((string)e.Element(Resource.XMLModel_Graph_Angle)),
                                DeviceWidth = int.Parse((string)e.Element(Resource.XMLModel_Graph_Width)),
                                DeviceHeight = int.Parse((string)e.Element(Resource.XMLModel_Graph_Height)),
                                MDString = (string)e.Element(Resource.XMLModel_MiscellaneousDevice_MDString),
                                MDBitmap = (string)e.Element(Resource.XMLModel_MiscellaneousDevice_MDBitmap),
                            };

                            dmGraphModel.Graph.GraphID = deviceGraphModels.Count;
                            dmGraphModel.MD.GraphID = deviceGraphModels.Count;

                            deviceGraphModels.Add(dmGraphModel);
                        }
                        break;
                    default:
                        break;
                }
            }

            return true;
        }

        static public bool SaveProject(string projectFile, ICollection<DeviceBaseModel> deviceModels, ICollection<DeviceBaseGraphModel> deviceGraphModels)
        {
            XElement project = new XElement(Resource.XMLModel_Project);

            XElement devices = new XElement(Resource.XMLModel_Devices);
            project.Add(devices);

            XElement graphs = new XElement(Resource.XMLModel_Graphs);
            project.Add(graphs);

            XElement axlesDevice = new XElement(Resource.XMLModel_Axles);
            devices.Add(axlesDevice);
            XElement axlesGraph = new XElement(Resource.XMLModel_Axles);
            graphs.Add(axlesGraph);

            XElement miscellaneousDevicesDevice = new XElement(Resource.XMLModel_MiscellaneousDevices);
            devices.Add(miscellaneousDevicesDevice);
            XElement miscellaneousDevicesGraph = new XElement(Resource.XMLModel_MiscellaneousDevices);
            graphs.Add(miscellaneousDevicesGraph);

            XElement platformsDevice = new XElement(Resource.XMLModel_Platforms);
            devices.Add(platformsDevice);
            XElement platformsGraph = new XElement(Resource.XMLModel_Platforms);
            graphs.Add(platformsGraph);

            XElement signalsDevice = new XElement(Resource.XMLModel_Signals);
            devices.Add(signalsDevice);
            XElement signalsGraph = new XElement(Resource.XMLModel_Signals);
            graphs.Add(signalsGraph);

            XElement switchsDevice = new XElement(Resource.XMLModel_Switches);
            devices.Add(switchsDevice);
            XElement switchsGraph = new XElement(Resource.XMLModel_Switches);
            graphs.Add(switchsGraph);

            XElement trackSegmentsDevice = new XElement(Resource.XMLModel_TrackSegments);
            devices.Add(trackSegmentsDevice);
            XElement trackSegmentsGraph = new XElement(Resource.XMLModel_TrackSegments);
            graphs.Add(trackSegmentsGraph);

            foreach (DeviceBaseModel deviceModel in deviceModels)
            {
                switch (deviceModel.GetType().Name)
                {
                    case "AxleModel":
                        AxleModel axModel = deviceModel as AxleModel;
                        
                        XElement axXML = new XElement(Resource.XMLModel_Axle,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(axModel.DeviceID)),
                        new XElement(Resource.XMLModel_Device_Type, axModel.DeviceType));

                        axlesDevice.Add(axXML);
                        
                        break;
                    case "MiscellaneousDeviceModel":
                        MiscellaneousDeviceModel mdModel = deviceModel as MiscellaneousDeviceModel;
                        
                        XElement mdXML = new XElement(Resource.XMLModel_MiscellaneousDevice,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(mdModel.DeviceID)),

                        new XElement(Resource.XMLModel_Device_Type, mdModel.DeviceType),
                        new XElement(Resource.XMLModel_MiscellaneousDevice_MDSubType, mdModel.MDSubType));

                        miscellaneousDevicesDevice.Add(mdXML);
                        
                        break;
                    case "PlatformModel":
                        PlatformModel pfModel = deviceModel as PlatformModel;
                        
                        XElement pfXML = new XElement(Resource.XMLModel_Platform,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(pfModel.DeviceID)),
                        new XElement(Resource.XMLModel_Device_Type, pfModel.DeviceType));

                        platformsDevice.Add(pfXML);
                        
                        break;
                    case "SignalModel":
                        SignalModel sgModel = deviceModel as SignalModel;
                        
                        XElement sgXML = new XElement(Resource.XMLModel_Signal,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(sgModel.DeviceID)),
                        new XElement(Resource.XMLModel_Device_Type, sgModel.DeviceType));

                        signalsDevice.Add(sgXML);
                        
                        break;
                    case "SwitchModel":
                        SwitchModel swModel = deviceModel as SwitchModel;
                        
                        XElement swXML = new XElement(Resource.XMLModel_Switch,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(swModel.DeviceID)),
                        new XElement(Resource.XMLModel_Device_Type, swModel.DeviceType));

                        switchsDevice.Add(swXML);
                        
                        break;
                    case "TrackSegmentModel":
                        TrackSegmentModel tsModel = deviceModel as TrackSegmentModel;
                        
                        XElement tsXML = new XElement(Resource.XMLModel_TrackSegment,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(tsModel.DeviceID)),
                        new XElement(Resource.XMLModel_Device_Type, tsModel.DeviceType));

                        trackSegmentsDevice.Add(tsXML);
                        
                        break;
                    default:
                        break;
                }
            }

            foreach (DeviceBaseGraphModel deviceGraphModel in deviceGraphModels)
            {
                switch (deviceGraphModel.GetType().Name)
                {
                    case "AxleGraphModel":
                        AxleGraphModel axGraphModel = deviceGraphModel as AxleGraphModel;

                        XElement axXML = new XElement(Resource.XMLModel_Axle,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(axGraphModel.DeviceID)),
                        new XElement(Resource.XMLModel_Graph_Name, axGraphModel.DeviceName),
                        new XElement(Resource.XMLModel_Graph_Type, axGraphModel.GraphType),
                        new XElement(Resource.XMLModel_Graph_PositionPoint, axGraphModel.PositionPoint),
                        new XElement(Resource.XMLModel_Graph_Width, axGraphModel.DeviceWidth),
                        new XElement(Resource.XMLModel_Graph_Height, axGraphModel.DeviceHeight),
                        new XElement(Resource.XMLModel_Graph_Angle, axGraphModel.DeviceAngle));

                        axlesGraph.Add(axXML);

                        break;
                    case "MiscellaneousDeviceGraphModel":
                        MiscellaneousDeviceGraphModel mdGraphModel = deviceGraphModel as MiscellaneousDeviceGraphModel;

                        XElement mdXML = new XElement(Resource.XMLModel_MiscellaneousDevice,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(mdGraphModel.DeviceID)),
                        new XElement(Resource.XMLModel_Graph_Name, mdGraphModel.DeviceName),
                        new XElement(Resource.XMLModel_Graph_Type, mdGraphModel.GraphType),
                        new XElement(Resource.XMLModel_Graph_PositionPoint, mdGraphModel.PositionPoint),
                        new XElement(Resource.XMLModel_Graph_Width, mdGraphModel.DeviceWidth),
                        new XElement(Resource.XMLModel_Graph_Height, mdGraphModel.DeviceHeight),
                        new XElement(Resource.XMLModel_Graph_Angle, mdGraphModel.DeviceAngle),
                        new XElement(Resource.XMLModel_MiscellaneousDevice_MDString, mdGraphModel.MDString),
                        new XElement(Resource.XMLModel_MiscellaneousDevice_MDBitmap, mdGraphModel.MDBitmap)
                        );

                        miscellaneousDevicesGraph.Add(mdXML);
                        
                        break;
                    case "PlatformGraphModel":
                        PlatformGraphModel pfGraphModel = deviceGraphModel as PlatformGraphModel;
                        
                        XElement pfXML = new XElement(Resource.XMLModel_Platform,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(pfGraphModel.DeviceID)),
                        new XElement(Resource.XMLModel_Graph_Name, pfGraphModel.DeviceName),
                        new XElement(Resource.XMLModel_Graph_Type, pfGraphModel.GraphType),
                        new XElement(Resource.XMLModel_Graph_PositionPoint, pfGraphModel.PositionPoint),
                        new XElement(Resource.XMLModel_Graph_Width, pfGraphModel.DeviceWidth),
                        new XElement(Resource.XMLModel_Graph_Height, pfGraphModel.DeviceHeight),
                        new XElement(Resource.XMLModel_Graph_Angle, pfGraphModel.DeviceAngle));

                        platformsGraph.Add(pfXML);
                        
                        break;
                    case "SignalGraphModel":
                        SignalGraphModel sgGraphModel = deviceGraphModel as SignalGraphModel;
                        
                        XElement sgXML = new XElement(Resource.XMLModel_Signal,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(sgGraphModel.DeviceID)),
                        new XElement(Resource.XMLModel_Graph_Name, sgGraphModel.DeviceName),
                        new XElement(Resource.XMLModel_Graph_Type, sgGraphModel.GraphType),
                        new XElement(Resource.XMLModel_Graph_PositionPoint, sgGraphModel.PositionPoint),
                        new XElement(Resource.XMLModel_Graph_Width, sgGraphModel.DeviceWidth),
                        new XElement(Resource.XMLModel_Graph_Height, sgGraphModel.DeviceHeight),
                        new XElement(Resource.XMLModel_Graph_Angle, sgGraphModel.DeviceAngle));

                        signalsGraph.Add(sgXML);
                        
                        break;
                    case "SwitchGraphModel":
                        SwitchGraphModel swGraphModel = deviceGraphModel as SwitchGraphModel;
                        
                        XElement swXML = new XElement(Resource.XMLModel_Switch,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(swGraphModel.DeviceID)),
                        new XElement(Resource.XMLModel_Graph_Name, swGraphModel.DeviceName),
                        new XElement(Resource.XMLModel_Graph_Type, swGraphModel.GraphType),
                        new XElement(Resource.XMLModel_Switch_MergePoint, swGraphModel.MergePoint),
                        new XElement(Resource.XMLModel_Switch_NormalPoint, swGraphModel.NormalPoint),
                        new XElement(Resource.XMLModel_Switch_ReversePoint, swGraphModel.ReversePoint));

                        switchsGraph.Add(swXML);
                        
                        break;
                    case "TrackSegmentGraphModel":
                        TrackSegmentGraphModel tsGraphModel = deviceGraphModel as TrackSegmentGraphModel;
                        
                        XElement tsXML = new XElement(Resource.XMLModel_TrackSegment,
                        new XElement(Resource.XMLModel_Device_ID, IntToHexString(tsGraphModel.DeviceID)),
                        new XElement(Resource.XMLModel_Graph_Name, tsGraphModel.DeviceName),
                        new XElement(Resource.XMLModel_Graph_Type, tsGraphModel.GraphType),
                        new XElement(Resource.XMLModel_TrackSegment_StartPoint, tsGraphModel.StartPoint),
                        new XElement(Resource.XMLModel_TrackSegment_EndPoint, tsGraphModel.EndPoint));

                        trackSegmentsGraph.Add(tsXML);
                        
                        break;
                    default:
                        break;
                }
            }

            project.Save(projectFile);
            return true;
        }

        static string IntToHexString(int value)
        {
            return string.Format("0x{0:X8}", value);
        }

        static int HexStringToInt(string value)
        {
            return Convert.ToInt32(value, 16);
        }
    }
}
